#include "recordtaskmanager.h"
#include "liverecorder.h"
#include "recordtask.h"
#include "usersettings.h"
#include <utility>

RecordTaskManager::RecordTaskManager(LiveRecorder* recorder)
    : QObject { recorder }, recorder_(recorder)
{
}

RecordTaskManager::~RecordTaskManager()
{
    stopAll();
}

bool RecordTaskManager::isRunning(int attention) const
{
    for (auto p : std::as_const(tasks_)) {
        if (p->attention() == attention) {
            return true;
        }
    }
    return false;
}

void RecordTaskManager::start(int attention)
{
    if (!isRunning(attention)
        && tasks_.size() < UserSettings::instance().recorderSettings().recorder_count) {
        auto t = new RecordTask(recorder_, attention, this);
        tasks_.push_back(t);
        connect(t, &RecordTask::aboutToStart, this, [this] {
            auto t = qobject_cast<RecordTask*>(sender());
            Q_ASSERT(t);
            Q_EMIT aboutToStart(t->attention());
        });
        connect(t, &RecordTask::positionChanged, this, [this](qint64 pos) {
            auto t = qobject_cast<RecordTask*>(sender());
            Q_ASSERT(t);
            Q_EMIT positionChanged(t->attention(), pos);
        });
        connect(t, &RecordTask::recordFinished, this,
                [this](const QString& filename, qint64 duration) {
                    auto t = qobject_cast<RecordTask*>(sender());
                    Q_ASSERT(t);
                    tasks_.removeOne(t);
                    Q_EMIT finished(t->attention(), filename, duration);
                    t->deleteLater();
                });
        connect(t, &RecordTask::failed, this, [this](int error, const QString& message) {
            auto t = qobject_cast<RecordTask*>(sender());
            Q_ASSERT(t);
            tasks_.removeOne(t);
            Q_EMIT failed(t->attention(), error, message);
            t->deleteLater();
        });
        t->start();
    }
}

void RecordTaskManager::stop(int attention)
{
    for (auto p : std::as_const(tasks_)) {
        if (p->attention() == attention) {
            p->stop();
            break;
        }
    }
}

void RecordTaskManager::stopAll()
{
    const auto tasks = tasks_;
    for (auto p : tasks) {
        p->stop();
    }
}

void RecordTaskManager::termiate(int attention)
{
    for (auto p : std::as_const(tasks_)) {
        if (p->attention() == attention) {
            disconnect(p, nullptr, this, nullptr);
            tasks_.removeOne(p);
            p->terminate();
            break;
        }
    }
}

void RecordTaskManager::termiateAll()
{
    const auto tasks = tasks_;
    tasks_.clear();
    for (auto p : tasks) {
        disconnect(p, nullptr, this, nullptr);
        p->terminate();
    }
}
